/************************************************
* @author:liyou
* @version: 1.0
* @description:
************************************************/

#include "init.h"
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <fstream>
#include <string>

#include <iostream>
#include <cassert>
#include <string>
#include <vector>
#include <openssl/sha.h>
#include <cstring>

using namespace std;


string Init::genger_string(int n)
{
//    srand((unsigned)time(nullptr));                        //产生随机化种子
    std::string str = "";
    for(int i=1;i <= n;i++)
    {
        int flag;
        flag = rand()%2;                     //随机使flag为1或0，为1就是大写，为0就是小写
        if(flag == 1)                        //如果flag=1
            str += rand()%('Z'-'A'+1)+'A';       //追加大写字母的ascii码
        else
            str += rand()%('z'-'a'+1)+'a';       //如果flag=0，追加为小写字母的ascii码

    }
    //cout<<str<<endl;                //将字符串输出
    return str;
}

string Init::com_string(string &onnx, string& engine) {

    std::string str = "";
    string head = "/usr/src/tensorrt/bin/trtexec --onnx=";
    string mid = " --workspace=4096 --saveEngine=";
    string end = " --fp16";
    str = head + onnx + mid + engine + end;

    //cout << str << endl;
    return str;
}

//int Init::cpp_callshell(string& call_string)
//{
//    FILE *fp = nullptr;
//    char buf[100]={0};
//    char serial[] = "1422622060246";
//    fp = popen("less /sys/firmware/devicetree/base/serial-number", "r");
//    if(fp) {
//
//        int ret = fread(buf,1,sizeof(buf)-1,fp);
//        if(ret > 0) {
//            std::cout << buf << std::endl;
//        }
//        pclose(fp);
//    }
//
//    std::cout <<strcmp(buf, serial) << std::endl;
//
//    if(strcmp(buf, serial))
//    {
//        std::cout << "success!!!" << std::endl;
//    }
//
//    return 0;
//}




//void encrypt_file(const char* in_file, const char* out_file, const unsigned char* key)
void Init::encrypt_file(string in_file, string out_file, string key)
{
    std::ifstream in(in_file, std::ios::binary);
    std::ofstream out(out_file, std::ios::binary);

    AES_KEY aes_key;
//    AES_set_encrypt_key(key, 128, &aes_key);  // 设置密钥和密钥长度
    AES_set_encrypt_key( (unsigned char *)key.c_str(), 128, &aes_key);  // 设置密钥和密钥长度



    // 加密文件
    while (in.good()) {
        unsigned char in_buf[AES_BLOCK_SIZE];
        unsigned char out_buf[AES_BLOCK_SIZE];
        in.read((char*)in_buf, AES_BLOCK_SIZE);

        int len = in.gcount();
//        int c = len % 16;
//        cout << len << "\t" << c << endl;
        if (len == 0)
            break;
        if(len % 16 == 0)
        {
            AES_encrypt(in_buf, out_buf, &aes_key);
            out.write((char*)out_buf, len);
        }
        else
        {
            out.write((char*)in_buf, len);
        }
    }
}
//void decrypt_file(const char* in_file, const char* out_file, const unsigned char* key)
void Init::decrypt_file(string in_file, string out_file, string key)
{
    std::ifstream in(in_file, std::ios::binary);
    std::ofstream out(out_file, std::ios::binary);

    AES_KEY aes_key;
    AES_set_decrypt_key((unsigned char *)key.c_str(), 128, &aes_key);  // 设置密钥和密钥长度


    char *trtModelStream{nullptr};
    size_t size{0};

    in.seekg(0, in.end);
    size = in.tellg();
    in.seekg(0, in.beg);
    trtModelStream = new char[size];

    // 解密文件
    int index = 0;
    while (in.good()) {
        unsigned char in_buf[AES_BLOCK_SIZE];
        unsigned char out_buf[AES_BLOCK_SIZE];
        in.read((char*)in_buf, AES_BLOCK_SIZE);


        int len = in.gcount();
//        int c = len % 16;
//
//        cout << len << "\t" << c << endl;
        if (len == 0)
            break;

        if(len % 16 == 0)
        {
            AES_decrypt(in_buf, out_buf, &aes_key);
//            memcpy(trtModelStream+index, (char*)out_buf,sizeof(char)*len);
            out.write((char*)out_buf, len);
        }
        else
        {
//            memcpy(trtModelStream+index, (char*)in_buf,sizeof(char)*len);
            out.write((char*)in_buf, len);
        }
        index += len;
    }
//    std::cout << index << " " << size << std::endl;
//    out.write(trtModelStream, size);
//    out.write((char*)trtModelStream, size);

}

int Init::disturb_file(std::string &in, std::string &out, int n, int i) {

    std::ifstream file(in, std::ios::binary);
    std::ofstream out_file(out, std::ios::binary);
    if (!file.good()) {
        std::cerr << "read " << in << " error!" << std::endl;
        return -1;
    }
    file.seekg(0, file.end);
    int size = file.tellg();
    file.seekg(0, file.beg);
    char* trtModelStream = new char[size];
    assert(trtModelStream);
    file.read(trtModelStream, size);
    file.close();

    int seq = size / (n+1);
    char* temp = nullptr;
    temp = new char[seq];
    memcpy(temp, (char*)trtModelStream+(i+1),sizeof(char)*seq);
    memcpy((char*)trtModelStream+(i+1), (char*)trtModelStream+(i),sizeof(char)*seq);
    memcpy((char*)trtModelStream+(i), temp, sizeof(char)*seq);

    out_file.write(trtModelStream, size);
    out_file.close();
    delete[] trtModelStream;
    delete[] temp;

    return 0;

}
